package com.krain.corelibrary.net;

import android.content.Context;
import android.os.Looper;
import android.support.v4.util.ArrayMap;
import android.text.TextUtils;
import android.util.Log;

import com.alibaba.fastjson.TypeReference;
import com.krain.corelibrary.constant.CoreKeys;
import com.krain.corelibrary.util.JsonUtil;
import com.krain.corelibrary.util.SpUtil;
import com.orhanobut.logger.Logger;
import com.squareup.okhttp.Callback;
import com.squareup.okhttp.FormEncodingBuilder;
import com.squareup.okhttp.Headers;
import com.squareup.okhttp.MediaType;
import com.squareup.okhttp.MultipartBuilder;
import com.squareup.okhttp.OkHttpClient;
import com.squareup.okhttp.Request;
import com.squareup.okhttp.RequestBody;
import com.squareup.okhttp.Response;

import java.io.File;
import java.io.IOException;
import java.lang.reflect.Array;
import java.net.SocketTimeoutException;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.TimeUnit;

/**
 * Class description
 * 总请求封装类的请求类
 * GET 和 POST请求都在这里完成
 *
 * @author yamin
 * @date 2015/12/8 下午 02:36
 */
public class NetClient {

    private static NetClient mHttpClient;

    private OkHttpClient mOkHttpClient;

    private static String baseurl;//请求的域名

    private NetClient(String baseurl) {
        this.baseurl = baseurl;
    }

    /**
     * 获取HttpClient的实例
     *
     * @param context
     * @return
     */
    public synchronized static NetClient getInstance(Context context) {
        if (mHttpClient == null)
            mHttpClient = new NetClient(SpUtil.getInstance(context.getApplicationContext()).getString(CoreKeys.SP_HOSTURL, ""));
        return mHttpClient;
    }

    /**
     * 初始化工作
     *
     * @param context
     * @param baseurl
     */
    public synchronized static void initHttp(Context context, String baseurl) {
        SpUtil.getInstance(context).putString(CoreKeys.SP_HOSTURL, baseurl);
        if (mHttpClient == null)
            mHttpClient = new NetClient(baseurl);
    }


    /**
     * 获取OKHTTP的client实例，保证
     *
     * @return
     */
    private synchronized OkHttpClient getClient() {
        if (mOkHttpClient == null)
            mOkHttpClient = new OkHttpClient();
        mOkHttpClient.setConnectTimeout(999, TimeUnit.SECONDS);
        mOkHttpClient.setReadTimeout(999, TimeUnit.SECONDS);
        mOkHttpClient.setWriteTimeout(999, TimeUnit.SECONDS);
        return mOkHttpClient;
    }


    /**
     * OkHttp上传文件
     * @param file
     * @return
     */
    public <T> T uploadFile(String methodUrl, File file,String fileName,Class<T> tClass){
        String result = "";
        T t = null;
        RequestBody fileBody = RequestBody.create(MediaType.parse("application/octet-stream"), file);
        RequestBody requestBody = new MultipartBuilder().type(MultipartBuilder.FORM).addFormDataPart(fileName,fileName, fileBody) .build();
        String url = new StringBuffer().append(baseurl).append(methodUrl).toString();
        Request request = new Request.Builder().url(url).post(requestBody).build();
        Logger.i(String.valueOf(request));
        try {
            Response response = getClient().newCall(request).execute();
            if (response != null && response.isSuccessful()) {
                result = response.body().string();
                Logger.json(result);
                t = JsonUtil.parseObject(result, tClass);
                return t;
            }
        } catch (IOException e) {
            e.printStackTrace();
            Logger.e("something exception in uploadFile e="+e.toString());
        } finally {
            return t;
        }
    }



    /**
     * OkHttp上传文件
     * @param files
     * @return
     */
    public <T> T uploadFiles(String methodUrl, ArrayList<File> files, String fileName, Class<T> tClass){
        String result = "";
        T t = null;
        MultipartBuilder builder  = new MultipartBuilder().type(MultipartBuilder.FORM);
        for (File f: files) {
            builder.addFormDataPart(fileName,fileName, RequestBody.create(MediaType.parse("application/octet-stream"), f));
        }
        RequestBody requestBody = builder.build();
        String url = new StringBuffer().append(baseurl).append(methodUrl).toString();
        Request request = new Request.Builder().url(url).post(requestBody).build();
        Logger.i(String.valueOf(request));
        try {
            Response response = getClient().newCall(request).execute();
            if (response != null && response.isSuccessful()) {
                result = response.body().string();
                Logger.json(result);
                t = JsonUtil.parseObject(result, tClass);
                return t;
            }
        } catch (IOException e) {
            e.printStackTrace();
            Logger.e("something exception in uploadFile e="+e.toString());
        } finally {
            return t;
        }
    }



    /**
     * 普通的GET请求
     *
     * @param method
     * @param params
     * @param <T>
     * @return
     */
    public <T> T get(Class<T> tClass, String method, ArrayMap params) {
        String result = "";
        StringBuffer strParams = new StringBuffer(baseurl);
        strParams.append(method);
        T t = null;
        try {
            Iterator<Map.Entry> it = params.entrySet().iterator();
            while (it.hasNext()) {
                Map.Entry e = it.next();
                strParams.append("&");
                strParams.append(e.getKey().toString());
                strParams.append("=");
                strParams.append(e.getValue().toString());
            }
            String url = new StringBuffer().append(strParams.toString()).toString();
            Request request = new Request.Builder().url(url).build();
            Logger.i(String.valueOf(request));
            Response response = getClient().newCall(request).execute();
            if (response != null && response.isSuccessful()) {
                result = response.body().string();
                Logger.json(result);
                t = JsonUtil.parseObject(result, tClass);
                return t;
            }
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            return t;
        }
    }


    /**
     * 普通的POST请求
     *
     * @param method
     * @param params
     * @param <T>
     * @return
     */
    public <T> T post(Class<T> tClass, String method, ArrayMap params) {
        T t = JsonUtil.parseObject(postResult(method, params), tClass);
        return t;
    }


    public String postResult(String method, ArrayMap params) {
        try {
            FormEncodingBuilder bodyBuilder = new FormEncodingBuilder();
            Iterator<Map.Entry> it = params.entrySet().iterator();
            while (it.hasNext()) {
                Map.Entry e = it.next();
                bodyBuilder.add(e.getKey().toString(), e.getValue().toString());
            }
            String url = new StringBuffer().append(baseurl).append(method).toString();
            Request request = new Request.Builder().url(url).post(bodyBuilder.build()).build();
            Logger.i(String.valueOf(request)+"params="+params.toString());
            Response response = getClient().newCall(request).execute();
            bodyBuilder = null;
            if (response != null && response.isSuccessful()) {
                String result = response.body().string();
                Logger.json(result);
                Logger.i(result);
                return result;
            } else {
                return null;
            }
        } catch (Exception e) {
            Logger.e("Exception="+e.toString());
            return null;
        }

    }


    public String getResult(String method, ArrayMap params) {
        String result = "";
        StringBuffer strParams = new StringBuffer(baseurl);
        strParams.append(method);
        try {
            Iterator<Map.Entry> it = params.entrySet().iterator();
            while (it.hasNext()) {
                Map.Entry e = it.next();
                strParams.append("&");
                strParams.append(e.getKey().toString());
                strParams.append("=");
                strParams.append(e.getValue().toString());
            }
            String url = new StringBuffer().append(strParams.toString()).toString();
            Logger.i("request="+url+"params="+params.toString());
            Request request = new Request.Builder().url(url).build();
            Response response = getClient().newCall(request).execute();
            if (response != null && response.isSuccessful()) {
                result = response.body().string();
                Logger.json(result);
                Logger.i(result);
                return result;
            }
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            return result;
        }
    }


    public <T> T requestListByPost(TypeReference typeReference, String methodUrl, ArrayMap<String, String> arrayMap) {
        String result = postResult(methodUrl,arrayMap);
        if (!TextUtils.isEmpty(result)){
            T t = (T) JsonUtil.parseObject(result, typeReference);
            return t;
        }else return null;
    }

    public <T> T requestListByGet(TypeReference typeReference, String methodUrl, ArrayMap<String, String> arrayMap) {
        String result = getResult(methodUrl,arrayMap);
        if (!TextUtils.isEmpty(result)){
            T t = (T) JsonUtil.parseObject(result, typeReference);
            return t;
        }else return null;
    }


}
